package com.wctj.api.security.component;

import cn.hutool.core.collection.CollUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.FilterInvocation;

import java.util.Collection;

/**
 * 动态权限决策管理器，用于判断用户是否有访问权限
 * @author carol
 */
@Slf4j
public class DynamicAccessDecisionManager implements AccessDecisionManager {

    @Override
    public void decide(Authentication authentication, Object object,
                       Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
        // 当接口未被配置资源时直接放行
        if (CollUtil.isEmpty(configAttributes)) {
            return;
        }
        for (ConfigAttribute configAttribute: configAttributes){
            log.info("configAttribute.getClass:{}",configAttribute.getClass().getName());
            //将访问所需资源或用户拥有资源进行比对
            String needAuthority = StringUtils.trim(configAttribute.getAttribute());
            for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) {
                log.info("grantedAuthority.getAuthority():{},needAuthority:{}",grantedAuthority.getAuthority(),needAuthority);
                if (grantedAuthority.getAuthority().equals(needAuthority)) {
                    return;
                }
            }
        }
        //TODO 暂时注释，放行所有
//        throw new AccessDeniedException("抱歉，您没有访问权限");
    }

    @Override
    public boolean supports(ConfigAttribute configAttribute) {
        return true;
    }

    @Override
    public boolean supports(Class<?> aClass) {
//        return true;
        return FilterInvocation.class.isAssignableFrom(aClass);
    }

}
